package triangleindex;
import java.awt.geom.Point2D;
import java.util.ArrayList;

public class Triangle {

	public Point2D center;
	// four kind of orientation decide the calculation of the co-ordination
	// 1-
	private int orientation; // 1-up; 2-down
	private int indexTriangle;
	private double radius;
	
	private int[] Ori_indexNode = new int[3]; // up - up,left,right / down -
	// down,right,life


	private int[] indexNode = new int[3]; // up - up,left,right / down -
	private int NewOrientation;
											// down,right,life

	public Triangle() {
		center = new Point2D.Float();
		orientation = 1;
		radius = 50;
	}
	
	public void copy(Triangle t) {
		// TODO Auto-generated method stub
		this.orientation = t.getOrientation();
		this.NewOrientation = t.getNewOrientation();
		this.setLocation(t.getX(), t.getY());
		this.setNodeIndex(t.getNodeIndex());
		this.setOriNodeIndex(t.getOriNodeIndex());
		this.setTriIndex(t.getTriIndex());
		this.setRadius(t.getRadius());
	}
	public Point2D getLocation() {
		return center;
	}

	public void setLocation(float x, float y) {
		center.setLocation(x, y);
	}

	public float getX() {
		return (float) center.getX();
	}

	public float getY() {
		return (float) center.getY();
	}

	// change the position of the triangle
	// rotate translate

	public void setX(float x) {
		this.center.setLocation(x, center.getY());
	}

	public void setY(float y) {
		this.center.setLocation(center.getX(), y);
	}

	public double getRadius() {
		return this.radius;
	}

	public void setRadius(double r) {
		this.radius = r;
	}

	public int getOrientation() {
		return this.orientation;
	}

	public void setOrientation(int o) {
		this.orientation = o;
	}

	public int getTriIndex() {
		return this.indexTriangle;
	}

	public void setTriIndex(int triindex) {
		this.indexTriangle = triindex;
	}

	public int[] getNodeIndex() {
		return this.indexNode;
	}
	
	public int[] getOriNodeIndex(){
		return this.Ori_indexNode;
	}
	
	public void setNewOrientation(int i) {
		// TODO Auto-generated method stub
		this.NewOrientation = i;
	}
	
	public int getNewOrientation(){
		return this.NewOrientation;
	}

	public void setNodeIndex(int[] nodeIndex) {
		this.indexNode[0] = nodeIndex[0];
		this.indexNode[1] = nodeIndex[1];
		this.indexNode[2] = nodeIndex[2];

	}
	
	public void setOriNodeIndex(int[] oriIndex) {
		// TODO Auto-generated method stub
		this.Ori_indexNode[0] = oriIndex[0];
		this.Ori_indexNode[1] = oriIndex[1];
		this.Ori_indexNode[2] = oriIndex[2];
	}


	public void rotate(double angle, int nodeindex) {
		int p = 0;
		for (int i = 0; i < 3; i++) {
			if (this.indexNode[i] == nodeindex) {
				p = i;
				break;
			}
		}

		Point2D axis = getNode(p);
		this.rotate(angle, axis);

	}

	
	
	// get the coordinate of one node
	public Point2D getNode(int p) {
		// TODO Auto-generated method stub
		Point2D node = new Point2D.Float();

		if (this.NewOrientation == 1)// up
		{
			switch (p) {
			case 0:
				node.setLocation(center.getX(), center.getY() - this.radius);
				break;
			case 1:
				node.setLocation(
						center.getX() - this.radius * Math.sin(Math.PI / 3.0),
						center.getY() + this.radius / 2.0);
				break;
			case 2:
				node.setLocation(
						center.getX() + this.radius * Math.sin(Math.PI / 3.0),
						center.getY() + this.radius / 2.0);
				break;
			}

		} else if (this.NewOrientation == 2) {
			switch (p) {
			case 0:
				node.setLocation(center.getX(), center.getY() + this.radius);
				break;
			case 1:
				node.setLocation(
						center.getX() + this.radius * Math.sin(Math.PI / 3.0),
						center.getY() - this.radius / 2.0);
				break;
			case 2:
				node.setLocation(
						center.getX() - this.radius * Math.sin(Math.PI / 3.0),
						center.getY() - this.radius / 2.0);
				break;

			}
		}
		return node;
	}

	// x,y is always the integrate times of radius*sin(PI/3) radius;
	public void translate(double x, double y) {
		center.setLocation(center.getX() + x, center.getY() + y);
	}

	public void rotate(double angle, Point2D axis) {

		// direction of the triangle
		Point2D dir = new Point2D.Float();
		dir.setLocation(center.getX() - axis.getX(),
				axis.getY() - center.getY());

		double ang = this.getAngle(dir);
		
		double angsum = ang + angle;
		if(angsum > Math.PI*2)
		{
			angsum -= Math.PI*2;
		}
		
		reSetCenter(angsum,axis);
			
	}

	

	public ArrayList<Point2D> getNode() {

		ArrayList<Point2D> nodes = new ArrayList<Point2D>();

		// anti-clockwise
		Point2D node1 = new Point2D.Float();
		Point2D node2 = new Point2D.Float();
		Point2D node3 = new Point2D.Float();

		nodes.add(node1);
		nodes.add(node2);
		nodes.add(node3);

		if (this.NewOrientation == 1) {
			node1.setLocation(this.center.getX(), this.center.getY()
					- this.radius);
			node2.setLocation(
					this.center.getX() - this.radius * Math.sin(Math.PI / 3.0),
					this.center.getY() + this.radius / 2.0);
			node3.setLocation(
					this.center.getX() + this.radius * Math.sin(Math.PI / 3.0),
					this.center.getY() + this.radius / 2.0);

		} else if (this.NewOrientation == 2) {

			node1.setLocation(this.center.getX(), this.center.getY()
					+ this.radius);
			node2.setLocation(
					this.center.getX() + this.radius * Math.sin(Math.PI / 3.0),
					this.center.getY() - this.radius / 2.0);
			node3.setLocation(
					this.center.getX() - this.radius * Math.sin(Math.PI / 3.0),
					this.center.getY() - this.radius / 2.0);
		}

		return nodes;

	}

	// very limited condition
	public double getAngle(Point2D vector) {
		//use 2 instead of 0 to ensure the buffer
		if(Math.abs(vector.getX())<1){
			vector.setLocation(0, vector.getY());
		}
		if(Math.abs(vector.getY())<1){
			vector.setLocation(vector.getX(), 0);
		}
		
		
		if ((vector.getX() > 0) && (vector.getY() > 0)) {
			return Math.PI / 6.0; // 30
		} else if ((vector.getX() == 0) && (vector.getY() > 0)) {
			return Math.PI * 3 / 6.0; // 90
		} else if ((vector.getX() < 0) && (vector.getY() > 0)) {
			return Math.PI * 5 / 6.0; // 120
		} else if ((vector.getX() < 0) && (vector.getY() < 0)) {
			return Math.PI * 7 / 6.0;
		} else if ((vector.getX() == 0) && (vector.getY() < 0)) {
			return Math.PI * 9 / 6.0;
		} else if ((vector.getX() > 0) && (vector.getY() < 0)) {
			return Math.PI * 11 / 6.0;
		}

		return 0;
	}
	
	private void reSetCenter(double angsum, Point2D axis) {
		if(angsum <0)
		{
			angsum = Math.PI*2 + angsum;
		}
		// TODO Auto-generated method stub
		/**
		if ((vector.getX() > 0) && (vector.getY() > 0)) {
			return Math.PI / 6.0; // 30
		} else if ((vector.getX() == 0) && (vector.getY() > 0)) {
			return Math.PI * 3 / 6.0; // 90
		} else if ((vector.getX() < 0) && (vector.getY() > 0)) {
			return Math.PI * 5 / 6.0; // 120
		} else if ((vector.getX() < 0) && (vector.getY() < 0)) {
			return Math.PI * 7 / 6.0;
		} else if ((vector.getX() == 0) && (vector.getY() < 0)) {
			return Math.PI * 9 / 6.0;
		} else if ((vector.getX() > 0) && (vector.getY() < 0)) {
			return Math.PI * 11 / 6.0;
		}
		*/
		
		if(Math.abs(angsum - Math.PI/6.0)< 0.005){
			center.setLocation((axis.getX() + this.radius * Math.cos(angsum)),
					(axis.getY() - this.radius * Math.sin(angsum)));
		}else if(Math.abs(angsum - Math.PI*3/6.0)< 0.005){
			center.setLocation((axis.getX() + this.radius * Math.cos(angsum)),
					(axis.getY() - this.radius * Math.sin(angsum)));
		}else if(Math.abs(angsum - Math.PI*5/6.0)<0.005){
			center.setLocation((axis.getX() + this.radius * Math.cos(angsum)),
					(axis.getY() - this.radius * Math.sin(angsum)));
		}else if(Math.abs(angsum - Math.PI*7/6.0)<0.005){
			center.setLocation((axis.getX() + this.radius * Math.cos(angsum)),
					(axis.getY() - this.radius * Math.sin(angsum)));
		}else if(Math.abs(angsum - Math.PI*9/6.0)<0.005){
			center.setLocation((axis.getX() + this.radius * Math.cos(angsum)),
					(axis.getY() - this.radius * Math.sin(angsum)));
		}else if(Math.abs(angsum - Math.PI*11/6.0)<0.005){
			center.setLocation((axis.getX() + this.radius * Math.cos(angsum)),
					(axis.getY() - this.radius * Math.sin(angsum)));
		}
		
	}

	// if the click point is inside the triangle
	public boolean isInside(float m_x, float m_y) {
		boolean isIn = false;

		// vector of MA,MB,MC
		ArrayList<Point2D> nodes = this.getNode();

		// MA
		point2d ma = new point2d(m_x - nodes.get(0).getX(), m_y
				- nodes.get(0).getY());
		point2d mb = new point2d(m_x - nodes.get(1).getX(), m_y
				- nodes.get(1).getY());
		point2d mc = new point2d(m_x - nodes.get(2).getX(), m_y
				- nodes.get(2).getY());

		int mamb = (int) (ma.x * mb.y - ma.y * mb.x);
		int mbmc = (int) (mb.x * mc.y - mb.y * mc.x);
		int mcma = (int) (mc.x * ma.y - mc.y * ma.x);

		if (((mamb >= 0) && (mbmc >= 0) && (mcma >= 0))
				|| ((mamb <= 0) && (mbmc <= 0) && (mcma <= 0))) {
			isIn = true;
		} else {
			isIn = false;
		}
		return isIn;
	}

	public void MoveToAd(Triangle triangle) {
		// TODO Auto-generated method stub

		int[] jointNode = this.findJointEdge(triangle);
		int pJointNode = this.findPysicalJointNode(triangle);

		// they are physically far far away
		if (pJointNode == -1) {
			
			this.translate(triangle, jointNode);

		} else {

			Point2D move1 = null;
			Point2D fix1 = null;
			Point2D cordinate = null;

			int differIndex = -1;
			int sameIndex = -1;
			if (jointNode[0] == pJointNode) {
				sameIndex = jointNode[0];
				differIndex = jointNode[1];

			} else if (jointNode[1] == pJointNode) {

				differIndex = jointNode[0];
				sameIndex = jointNode[1];

			}

			// the fixed one is

			int[] indexes1 = this.getNodeIndex();
			int d1 = 0;
			for (int i = 0; i < 3; i++) {
				if (differIndex == indexes1[i]) {
					d1 = i;
				}
			}
			move1 = this.getNode(d1);
           
			int[] indexes2 = this.getNodeIndex();
			int d2 = 0;
			for (int i = 0; i < 3; i++) {
				if (differIndex == indexes2[i]) {
					d2 = i;
				}
			}
			fix1 = triangle.getNode(d2);

			int[] indexes3 = this.getNodeIndex();
			int d3 = -1;
			for (int i = 0; i < 3; i++) {
				if (sameIndex == indexes3[i]) {
					d3 = i;
					break;
				}
			}
			cordinate = this.getNode(d3);

			Point2D moveAxis = new Point2D.Float();
			Point2D fixAxis = new Point2D.Float();
            
			// we should just use the center of the triangle 
			// but we keep it for a while
			/**
			moveAxis.setLocation(move1.getX() - cordinate.getX(), - (move1.getY()
					- cordinate.getY()));
			fixAxis.setLocation(fix1.getX() - cordinate.getX(),
					-(fix1.getY() - cordinate.getY()));
			**/
			
			moveAxis.setLocation(this.getX() - cordinate.getX(), - (this.getY()
					- cordinate.getY()));
			fixAxis.setLocation(triangle.getX() - cordinate.getX(),
					-(triangle.getY() - cordinate.getY()));
			
			/**
			double movedis = Math.sqrt(moveAxis.getX() * moveAxis.getX()
					+ moveAxis.getY() * moveAxis.getY());
			moveAxis.setLocation(moveAxis.getX() / movedis, moveAxis.getY()
					/ movedis);

			double fixdis = Math.sqrt(fixAxis.getX() * fixAxis.getX()
					+ fixAxis.getY() * fixAxis.getY());
			
			
			fixAxis.setLocation(fixAxis.getX() / movedis, fixAxis.getY()
					/ movedis);
            **/
			double angle1 = this.getAngle(moveAxis);
			double angle2 = this.getAngle(fixAxis);
			
			double angle = Math.PI / 3.0;
			
			if(angle1 > angle2){
				if((angle1 - angle2)> Math.PI)
				{
				}else{
					angle = - angle;
				}
			}else if(angle1<angle2){
				if((angle2 - angle1)> Math.PI){
					angle = - angle;
				}else{
					
				}
			}
			
			/**
			double angle = Math
					.acos((moveAxis.getX() * fixAxis.getX() + moveAxis.getY()
							* fixAxis.getY())
							/ (Math.sqrt(moveAxis.getX() * moveAxis.getX()
									+ moveAxis.getY() + moveAxis.getY()) * Math
										.sqrt(fixAxis.getX() * fixAxis.getX()
												+ fixAxis.getY()
												* fixAxis.getY())));
			
			System.out.println(angle);
             */
			
			
			/**
			angle = Math.PI / 3.0;
			if (this.orientation == 1) {
				if ((move1.getX() < fix1.getX())
						|| ((move1.getX() > fix1.getX()) && (move1.getY() == fix1
								.getY()))) {

				} else {
					angle = -angle;
				}

			} else if (this.orientation == 2) {
				if ((move1.getX() > fix1.getX())
						&& (move1.getY() > fix1.getY())
						|| ((move1.getX() < fix1.getX()) && (move1.getY() == fix1
								.getY()))) {

				} else {
					angle = -angle;
				}

			}
			**/
			
			
		
			
			this.rotate(angle, pJointNode);
	//		System.out.println(angle);
			setNodeIndex(angle, pJointNode);
		}

	}

	private void setNodeIndex(double angle, int pJointNode) {
		// TODO Auto-generated method stub
		int num = -1 ;
		for(int i = 0 ; i <3; i++ ){
			if(this.indexNode[i] == pJointNode){
				num = i;
				break;
			}
		}
		
		if(angle != 0)
		{
			if (this.NewOrientation == 1) {
				if(angle <0) // anti-clock
				{
					int temp = this.indexNode[1]; 
					this.indexNode[1] = this.indexNode[0];
					this.indexNode[0] = this.indexNode[2];
					this.indexNode[2] = temp;
				}else if(angle > 0){
					int temp = this.indexNode[1]; 
					this.indexNode[1] = this.indexNode[2];
					this.indexNode[2] = this.indexNode[0];
					this.indexNode[0] = temp;
				}
				this.NewOrientation = 2;
			} else if (this.NewOrientation == 2) {
				
				if(angle >0) // anti-clock
				{
					int temp = this.indexNode[0]; 
					this.indexNode[0] = this.indexNode[1];
					this.indexNode[1] = this.indexNode[2];
					this.indexNode[2] = temp;
				}else if(angle < 0){
					int temp = this.indexNode[2]; 
					this.indexNode[2] = this.indexNode[1];
					this.indexNode[1] = this.indexNode[0];
					this.indexNode[0] = temp;
				}
				this.NewOrientation = 1;
			}
		}
		
		
	}

	private void translate(Triangle triangle, int[] jointNode) {
		// TODO Auto-generated method stub
		
		
		int fixIndex1 = -1;
		int fixIndex2 = -1;
		for(int i = 0; i <3; i ++)
		{
			if(triangle.getNodeIndex()[i] == jointNode[0])
			{
				fixIndex1 = i;
			}
			if(triangle.getNodeIndex()[i] == jointNode[1])
			{
				fixIndex2 = i;
			}
		}
		
		int ownNodeIndex = -1;
		for(int i = 0 ; i < 3; i ++)
		{
			if((this.getNodeIndex()[i] != jointNode[0])&&(this.getNodeIndex()[i] != jointNode[1])){
				ownNodeIndex = this.getNodeIndex()[i];
			}
		}
		
		Point2D fix1 = triangle.getNode(fixIndex1);
		Point2D fix2 = triangle.getNode(fixIndex2);
		
		//every orientation, there are three posible changes
		if(triangle.NewOrientation == 1)
		{

			this.NewOrientation = 2;
			if(((fixIndex1 == 0)&&(fixIndex2 == 1))||((fixIndex1 == 1)&&(fixIndex2 == 0))){
				
				this.center.setLocation(triangle.center.getX() - (float) (this.radius * Math.sin(Math.PI/3.0)), triangle.center.getY() - this.radius/2.0 );
				int[] newIndex = {triangle.getNodeIndex()[1],triangle.getNodeIndex()[0],ownNodeIndex };
				
			    this.setNodeIndex(newIndex);
				
			}else if(((fixIndex1 == 1)&&(fixIndex2 == 2))||((fixIndex1 == 2)&&(fixIndex2 == 1))){
				this.center.setLocation(triangle.center.getX(), triangle.center.getY() + this.radius);

				int[] newIndex = {ownNodeIndex, triangle.getNodeIndex()[2],triangle.getNodeIndex()[1]};
				
			    this.setNodeIndex(newIndex);
			    
			}else if(((fixIndex1 == 0)&&(fixIndex2 == 2))||((fixIndex1 == 2)&&(fixIndex2 == 0))){
				this.center.setLocation(triangle.center.getX() + (float) (this.radius * Math.sin(Math.PI/3.0)), triangle.center.getY() - this.radius/2.0 );

				int[] newIndex = {triangle.getNodeIndex()[2],ownNodeIndex, triangle.getNodeIndex()[0]};
				
			    this.setNodeIndex(newIndex);
			}
			
		}else if (triangle.NewOrientation == 2)
		{
		
			this.NewOrientation = 1;
			if(((fixIndex1 == 0)&&(fixIndex2 == 1))||((fixIndex1 == 1)&&(fixIndex2 == 0))){
				
				this.center.setLocation(triangle.center.getX() + (float) (this.radius * Math.sin(Math.PI/3.0)), triangle.center.getY() + this.radius/2.0 );
				
					int[] newIndex = {triangle.getNodeIndex()[1],triangle.getNodeIndex()[0], ownNodeIndex};
						
				    this.setNodeIndex(newIndex);
				
				
			}else if(((fixIndex1 == 1)&&(fixIndex2 == 2))||((fixIndex1 == 2)&&(fixIndex2 == 1))){
				this.center.setLocation(triangle.center.getX(), triangle.center.getY() - this.radius);
				
				int[] newIndex = {ownNodeIndex, triangle.getNodeIndex()[2],triangle.getNodeIndex()[1]};
				
			    this.setNodeIndex(newIndex);
				
			}else if(((fixIndex1 == 0)&&(fixIndex2 == 2))||((fixIndex1 == 2)&&(fixIndex2 == 0))){
				this.center.setLocation(triangle.center.getX() - (float) (this.radius * Math.sin(Math.PI/3.0)), triangle.center.getY() + this.radius/2.0 );

				int[] newIndex = {triangle.getNodeIndex()[2],ownNodeIndex, triangle.getNodeIndex()[0]};
				
			    this.setNodeIndex(newIndex);
			}
		}
		
		
	}

	
	public int[] findJointEdge(Triangle triangle) {
		int[] index = new int[2];

		int count = -1;

		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				if (this.getNodeIndex()[i] == triangle.getNodeIndex()[j]) {
					count++;
					index[count] = this.getNodeIndex()[i];
					if (count == 1) {
						break;
					}
				}
			}

		}
		return index;
	}

	// this is the physical joint point.
	public int findPysicalJointNode(Triangle tri) {
		ArrayList<Point2D> moveTri = this.getNode();
		ArrayList<Point2D> fixTri = tri.getNode();

		int nodeIndex = -1; // move first, fixed second
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				
				double disx = moveTri.get(i).getX() - fixTri.get(j).getX();
				double disy = moveTri.get(i).getY() - fixTri.get(j).getY();
				if((Math.abs(disx) <2.0)&&(Math.abs(disy) <2.0))
				{
					nodeIndex = this.getNodeIndex()[i];
					break;
				}
			}

		}

		return nodeIndex;
	}

	
	
	public void translateToScreen(ArrayList<Triangle> adjTri) {
		for(int i = 0 ; i < 3; i ++)
		{
		  
			if(this.isFarAdjecent(adjTri.get(i))){
			   int[] jointNode = this.findJointEdge(adjTri.get(i));
			   if(!((jointNode[0]==0)&&(jointNode[1]==0)))
			   this.translate(adjTri.get(i), jointNode);
			   break;
		   }
		}

	}
	
	
	
	
	
	public boolean isEdgeAdjecent(Triangle t)
	{
		if(this.center.distance(t.center) == this.radius)
		{
			return true;
		}else{
			return false;
		}
		
		
	}
	
	public boolean isNodeAdjecent(Triangle t)
	{
		double dis = this.center.distance(t.center);
		if((dis > this.radius)&&(dis <= this.radius*2))
		{
			return true;
		}else{
			return false;
		}
		
	}
	
	public boolean isFarAdjecent(Triangle t)
	{
		if(this.center.distance(t.center) > this.radius*2)
		{
			return true;
		}else{
			return false;
		}
		
		
	}

	/*
	 * adjust the shape, if it is end at two edge, then one more points shout be added
	 */
	public void adjustShape(int[] groupx, int[] groupy, int size) {
		// TODO Auto-generated method stub
		int dif_x = groupx[size-1] - groupx[0];
		int dif_y = groupy[size-1] - groupy[0];
		
		if(dif_x == 0)
		{
			return;
		}
		
		double angle = Math.atan(dif_y/dif_x);
		
//		System.out.println("angle :" + angle);
		
		if((Math.abs(angle - Math.PI/3.0) < 0.2 )||(Math.abs(angle + Math.PI/1.0) < 0.2)||(Math.abs(angle - 0)<0.2 ))
		{
			
		}else{
			Point2D start = new Point2D.Float(groupx[0], groupy[0]);
			Point2D end = new Point2D.Float(groupx[size-1], groupy[size-1]);
			
			if(getAddNode(start, end)!= -1){
			groupx[size] = (int) this.getNode().get(getAddNode(start,end)).getX();
			groupy[size] = (int) this.getNode().get(getAddNode(start,end)).getY();
			size ++;
			}
		}
		
	}

	
	/*
	 * get the joint point
	 */
	
	public int getAddNode(Point2D start, Point2D end){
		
		int node = -1;
		float dis = 10000;
		int ns = 0;
		int ne = 0;
		float[] tempdis = new float[3];
		
		tempdis[0] = GetPointToLineDistance(this.getNode().get(0),this.getNode().get(1),start);
		tempdis[1] = GetPointToLineDistance(this.getNode().get(1),this.getNode().get(2),start);
		tempdis[2] = GetPointToLineDistance(this.getNode().get(2),this.getNode().get(0),start);
		
		for(int i = 0 ; i < 3; i++){
			if(tempdis[i]<dis)
			{
				dis = tempdis[i];
				ns = i;
			}
		}
		
		tempdis[0] = GetPointToLineDistance(this.getNode().get(0),this.getNode().get(1),end);
		tempdis[1] = GetPointToLineDistance(this.getNode().get(1),this.getNode().get(2),end);
		tempdis[2] = GetPointToLineDistance(this.getNode().get(2),this.getNode().get(0),end);
		
		dis = 10000;
		for(int i = 0 ; i < 3; i++){
			if(tempdis[i]<dis)
			{
				dis = tempdis[i];
				ne = i;
			}
		}
		
		if(((ns == 0)&&(ne == 1))||((ns == 1)&&(ne == 0))){
			node = 1;
		}
		
		if(((ns == 1)&&(ne == 2))||((ns == 2)&&(ne == 1))){
			node = 2;
		}
		
		if(((ns == 2)&&(ne == 0))||((ns == 0)&&(ne == 2))){
			node = 0;
		}
		
		return node; 
	}
	
	
	/**
	 * calculate the inside points to the three edges
	 */
	
	double GetPointDistance(Point2D p1, Point2D p2) 
	{
	 return Math.sqrt((p1.getX()-p2.getX())*(p1.getX()-p2.getX())+(p1.getY()-p2.getY())*(p1.getY()-p2.getY()));
	}
	
	float GetPointToLineDistance(Point2D PA, Point2D PB, Point2D P3) // linenode1,linenode2, otherpoint
	{

	
	 float a,b,c;
	 a = (float) GetPointDistance(PB,P3);
	 if(a<=0.00001)
	  return 0.0f;
	 b = (float) GetPointDistance(PA,P3);
	 if(b<=0.00001)
	  return 0.0f;
	 c = (float) GetPointDistance(PA,PB);
	 if(c<=0.00001)
	  return a;
	
	 if(a*a>=b*b+c*c)
	  return b;      
	 if(b*b>=a*a+c*c)
	  return a;      
	 
	
	 float l=(a+b+c)/2;    
	 float s= (float) Math.sqrt(l*(l-a)*(l-b)*(l-c)); 
	 return 2*s/c;
	}

	public double getTextureType() {
		// TODO Auto-generated method stub
		// 1,2,3,4,5,6
		
		int head = this.indexNode[0];
		
		if(this.orientation == 1){
			if(this.NewOrientation == 1){
				if(head == this.Ori_indexNode[0])
		    	{
		    		return 0;
		    	}else if(head == this.Ori_indexNode[1]){ //rotate 120 left
		    		return -Math.PI*2/3;
		    	}else if(head == this.Ori_indexNode[2]){  //rotate 240
		    		return -Math.PI*4/3;
		    	}
			}else if(this.NewOrientation == 2){
				if(head == this.Ori_indexNode[2])
				{
					return Math.PI/3.0;
				}else if(head == this.Ori_indexNode[1]){
					return -Math.PI/3.0;
				}else if(head == this.Ori_indexNode[0])
					return Math.PI;
			}
		}else if(this.orientation == 2){
			if(this.NewOrientation == 2){
				if(head == this.Ori_indexNode[0])
		    	{
		    		return Math.PI;
		    	}else if(head == this.Ori_indexNode[1]){ //rotate 120 left
		    		return Math.PI*2/3 + Math.PI;
		    		
		    	}else if(head == this.Ori_indexNode[2]){  //rotate 240
		    		return Math.PI*4/3 + Math.PI;
		    	}
			}else if(this.NewOrientation == 1){
				if(head == this.Ori_indexNode[2]){
					return -Math.PI*2/3.0;
				}else if(head == this.Ori_indexNode[1]){
					return Math.PI*2/3.0;
				}else if(head == this.Ori_indexNode[0]){
					return Math.PI;
				}
			}
		}
		
		return 0;
	}

	
	public double getRotate(Triangle b) {
		// TODO Auto-generated method stub

		Point2D cordinate = this.getPhysicalJointNode(b);

		Point2D moveAxis = new Point2D.Float();
		Point2D fixAxis = new Point2D.Float();

		// we should just use the center of the triangle

		moveAxis.setLocation(this.getX() - cordinate.getX(),
				-(this.getY() - cordinate.getY()));
		fixAxis.setLocation(b.getX() - cordinate.getX(),
				-(b.getY() - cordinate.getY()));

		double angle1 = this.getAngle(moveAxis);
		double angle2 = this.getAngle(fixAxis);

		double angle = Math.PI / 3.0;

		if (angle1 > angle2) {
			if ((angle1 - angle2) > Math.PI) {
			} else {
				angle = -angle;
			}
		} else if (angle1 < angle2) {
			if ((angle2 - angle1) > Math.PI) {
				angle = -angle;
			} else {

			}
		}

		return angle;

	}
	
	
	public Point2D getPhysicalJointNode(Triangle e) {
		// TODO Auto-generated method stub
		
		Point2D p = new Point2D.Float();
		
		ArrayList<Point2D> bnode = this.getNode(); 
		ArrayList<Point2D> enode = e.getNode();       
		        
		for(int i = 0 ; i < 3; i ++)
		{
			for(int j = 0 ; j < 3; j ++)
			{
				float dis = (float) Math.sqrt(((bnode.get(i).getX()-enode.get(j).getX())*(bnode.get(i).getX()-enode.get(j).getX())) + ((bnode.get(i).getY()-enode.get(j).getY())*(bnode.get(i).getY()-enode.get(j).getY())));
				if(dis<2){
					p.setLocation(bnode.get(i));
					return p;
				}	
				
			}
		}
		
		return null;
	}

	public Point2D getDistance(Triangle byIndex) {
		// TODO Auto-generated method stub
		
		
		return null;
	}


	
	/**
	
    public float intersectSegement( point2d p3, point2d p4) {
			  float numerator12 = (p4.getX() - p3.getX()) * (p1.getY() - p3.getY())
			    - (p4.getY() - p3.getY()) * (p1.getX() - p3.getX());
			  float denominator12 = (p4.getY() - p3.getY()) * (p2.getX() - p1.getX())
			    - (p4.getX() - p3.getX()) * (p2.getY() - p1.getY());

			  float numerator34 = (p2.getX() - p1.getX()) * (p1.getY() - p3.getY()) - (p2.getY() - p1.getY())
			    * (p1.getX() - p3.getX());
			  float denominator34 = (p4.getY() - p3.getY()) * (p2.getX() - p1.getX())
			    - (p4.getX() - p3.getX()) * (p2.getY() - p1.getY());

			  if (denominator12 == 0 || denominator34 == 0)
			   return -1;
			  else if (numerator12 / denominator12 >= 0
			    && numerator12 / denominator12 < 1
			    && numerator34 / denominator34 >= 0
			    && numerator34 / denominator34 < 1) {
			   float t = p3.getZ() + numerator34 / denominator34
			     * (p4.getZ() - p3.getZ());
			   if (t >= z && t < z + height) {
			    return t;
			   }
			  }

			  return -1;
			 
	}
	
	**/
	
	
	
	
}
